﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.IO;

namespace ProjectResistance
{
    internal static class Utility
    {
        private static BandColor[] GetBands(decimal resistance)
        {
            BandColor[] bands = new BandColor[3];

            char[] chars;
            long whole = (long)resistance;
            bool band3Set = false;

            if (whole < 1)
            {
                bands[2] = BandColor.Silver;
                chars = (resistance * 100).ToString().Substring(0, 2).ToCharArray();
                band3Set = true;
            }
            else if (whole < 10)
            {
                bands[2] = BandColor.Gold;
                chars = (resistance * 10).ToString().Substring(0, 2).ToCharArray();
                band3Set = true;
            }
            else
            {
                chars = whole.ToString().ToCharArray();
            }

            bands[0] = (BandColor)(int)chars[0] - 48;
            bands[1] = (BandColor)(int)chars[1] - 48;

            if (!band3Set)
            {
                // how many digits remain?
                if (chars.Length >= 2)
                {
                    bands[2] = (BandColor)chars.Length - 2;
                }
                else
                {
                    if ((resistance - whole) > 0)
                    {
                        // TODO: handle decimal values
                    }
                    throw new NotSupportedException();
                }
            }
            return bands;
        }

        public static BandColor[] GetBands(decimal resistance, ToleranceValues tolerance)
        {
            if (resistance < 0) throw new ArgumentOutOfRangeException();
            BandColor[] bands = new BandColor[4];
            Array.Copy(GetBands(resistance), bands, 3);
            bands[3] = GetToleranceColor(tolerance);
            return bands;
        }

        public static decimal GetResistance(BandColor[] bands)
        {
            if (bands == null) throw new ArgumentNullException();
            if ((bands.Length < 3) || (bands.Length > 4)) throw new ArgumentOutOfRangeException();

            // first 2 digits
            int value = ((int)bands[0] * 10) + (int)bands[1];

            // multiplier
            return (decimal)value * (decimal)Math.Pow(10, (int)bands[2]);
        }

        public static ToleranceValues GetTolerance(BandColor color)
        {
            return (ToleranceValues)color;
        }

        public static BandColor GetToleranceColor(ToleranceValues tolerance)
        {
            return (BandColor)tolerance;
        }

        public static decimal ResistanceUp(decimal resistance, int digit)
        {
            if ((digit <= 0) || (digit > 3)) throw new ArgumentOutOfRangeException();

            // TODO: do we need to handle resistance from 0.9 to 9?  I'm fairly sure this will break for those

            List<char> chars = new List<char>(resistance.ToString().ToCharArray());

            switch (digit)
            {
                case 1:
                case 2:
                    int d = (int)chars[digit - 1] - 48;
                    d++;
                    if (d > 9)
                    {
                        d = 0;
                    }
                    chars[digit - 1] = (char)(d + 48);
                    resistance = int.Parse(new string(chars.ToArray()));
                    break;
                case 3: // multiplier
                    if (chars.Count < 11)
                    {
                        resistance *= 10;
                    }
                    else
                    {
                        // need to wrap from white back to silver
                        resistance = decimal.Parse(new string(new char[] {chars[0], chars[1]})) / 100;
                    }
                    break;
            }

            return resistance;
        }

        public static decimal ResistanceDown(decimal resistance, int digit)
        {
            if ((digit <= 0) || (digit > 3)) throw new ArgumentOutOfRangeException();

            List<char> chars = new List<char>(resistance.ToString().ToCharArray());

            switch (digit)
            {
                case 1:
                case 2:
                    int d = (int)chars[digit - 1] - 48;
                    d--;
                    if (d < 0)
                    {
                        d = 9;
                    }
                    chars[digit - 1] = (char)(d + 48);
                    resistance = int.Parse(new string(chars.ToArray()));
                    break;
                case 3: // multiplier
                    resistance /= 10;
                    if (resistance < (decimal)0.1)
                    {
                        // need to wrap from silver back up to white
                        resistance = (decimal)Math.Floor((double)resistance * 1000D) * 1000000000M;
                        
                    }

                    break;
            }
            
            return resistance;
        }
    }
}
